"use strict";

import Vue from 'vue';
import config from './config/index';
import jude from './Tools/Jude';
import { Storage } from './Storage/index.js';
import { debounce } from './lodash/throttle';

const queryString = require('query-string');

const LOCATION = {
    hash: "",
    host: "",
    hostname: "",
    href: "",
    origin: "",
    pathname: "",
    port: "",
    protocol: "",
    search: "",
    query: null
};

class QueryString {
    constructor () {
        this.location = {
            hash: "",
            host: "",
            hostname: "",
            href: "",
            origin: "",
            pathname: "",
            port: "",
            protocol: "",
            search: ""
        };
    }

    stringify (obj, sep, eq) {
        const options = arguments[arguments.length - 1];
        sep = sep || '&';
        eq = eq || '=';
        let that = this;
        let encode = encodeURIComponent;
        if (!jude.isEmptyObject(options)) {
            switch (true) {
                case typeof options.encodeURIComponent === 'function':
                    encode = options.encodeURIComponent;
                case options.isEncode === false:
                    encode = v => v;
                case options.sep:
                    sep = options.sep;
                case options.eq:
                    eq = options.eq;
            }
        }
        if (obj !== null && typeof obj === 'object') {
            let keys = Object.keys(obj);
            let len = keys.length;
            let flast = len - 1;
            let fields = '';
            for (let i = 0; i < len; ++i) {
                let k = keys[i];
                let v = obj[k];
                let ks = encode(that.stringifyPrimitive(k)) + eq;
                if (Array.isArray(v)) {
                    let vlen = v.length;
                    let vlast = vlen - 1;
                    for (let j = 0; j < vlen; ++j) {
                        fields += ks + encode(that.stringifyPrimitive(v[j]));
                        if (j < vlast)
                            fields += sep;
                    }
                    if (vlen && i < flast)
                        fields += sep;
                } else {
                    fields += ks + encode(that.stringifyPrimitive(v));
                    if (i < flast)
                        fields += sep;
                }
            }
            return fields;
        }
        return '';
    }

    parse (url, bol = false) {
        if (bol === true) return this.queryString(url).query;
        return this.queryString(url);
    }

    parseScene (path) {
        const a = decodeURIComponent(path);
        const query = this.parse(a, true);
        if (query.scene) {
            const path = `https://res.tuoluocard.com?${query.scene}`
            return this.parse(path, true)
        } else {
            return query
        }
    }

    stringifyPrimitive (v) {
        if (typeof v === 'string')
            return v;
        if (typeof v === 'number' && isFinite(v))
            return '' + v;
        if (typeof v === 'boolean')
            return v ? 'true' : 'false';
        return '';
    }

    escape (str) {
        if (typeof str !== 'string') {
            if (typeof str === 'object')
                str = String(str);
            else
                str += '';
        }
        let out = '';
        let lastPos = 0;

        for (let i = 0; i < str.length; ++i) {
            let c = str.charCodeAt(i);

            // ASCII
            if (c < 0x80) {
                if (noEscape[c] === 1)
                    continue;
                if (lastPos < i)
                    out += str.slice(lastPos, i);
                lastPos = i + 1;
                out += hexTable[c];
                continue;
            }

            if (lastPos < i)
                out += str.slice(lastPos, i);

            // Multi-byte characters ...
            if (c < 0x800) {
                lastPos = i + 1;
                out += hexTable[0xC0 | (c >> 6)] + hexTable[0x80 | (c & 0x3F)];
                continue;
            }
            if (c < 0xD800 || c >= 0xE000) {
                lastPos = i + 1;
                out += hexTable[0xE0 | (c >> 12)] +
                    hexTable[0x80 | ((c >> 6) & 0x3F)] +
                    hexTable[0x80 | (c & 0x3F)];
                continue;
            }
            // Surrogate pair
            ++i;
            let c2;
            if (i < str.length)
                c2 = str.charCodeAt(i) & 0x3FF;
            else
                throw new URIError('URI malformed');
            lastPos = i + 1;
            c = 0x10000 + (((c & 0x3FF) << 10) | c2);
            out += hexTable[0xF0 | (c >> 18)] +
                hexTable[0x80 | ((c >> 12) & 0x3F)] +
                hexTable[0x80 | ((c >> 6) & 0x3F)] +
                hexTable[0x80 | (c & 0x3F)];
        }
        if (lastPos === 0)
            return str;
        if (lastPos < str.length)
            return out + str.slice(lastPos);
        return out;
    }

    queryString (href) {
        let __location = {...LOCATION};
        // href = decodeURIComponent(href);
        if (typeof href !== 'string') {
            return __location;
        }
        __location.query = {};
        __location.href = href;
        const v1 = href.split('#');
        __location.hash = v1[1] ? '#' + v1[1] : '';
        let href_1 = v1[0];
        let href_2 = v1[1];
        if (typeof href_1 === "string") {
            const v2 = href_1.split('?');
            href_1 = v2[0];
            __location.search = v2[1] ? '?' + v2[1] : '';
        }
        if (typeof href_1 === "string") {
            const v3 = href_1.split('//');
            href_1 = v3[1];
            __location.protocol = v3[0] || '';
        }
        if (typeof href_1 === "string") {
            const v4 = href_1.split('/');
            __location.pathname = href_1 = '/' + v4.slice(1).join('/');
            __location.hostname = v4[0] || '';
            if (__location.hostname.indexOf(':') > -1) {
                const v5 = __location.hostname.split(':');
                __location.host = v5[0] || '';
                __location.port = v5[1] || '';
            } else {
                __location.host = __location.hostname;
            }
        }
        __location.origin = __location.protocol + '//' + __location.hostname;
        __location.query = queryString.parse(__location.search);

        if (typeof href_2 === "string") {
            const v21 = href_2.split('?');
            __location.pathname2 = __location.pathname;
            __location.pathname = v21[0];
            __location.search2 = __location.search;
            const query = __location.query;
            __location.query = {...query, ...queryString.parse(v21[1] || '')};
            __location.query2 = query;
            const search = queryString.stringify(__location.query);
            __location.search = search ? '?' + search : '';
        }
        return __location;
    }

    parse2 (src = '') {
        let obj = {};
        if (/\;/g.test(src) && /\=/g.test(src)) {
            let arr = src.split(/\=+|\;+/g)
            arr.forEach((value, index, array) => {
                if (index % 2 === 1) {
                    obj[array[index - 1]] = value
                }
            })
            return obj
        } else {
            return {}
        }
    }

    // queryString (href) {
    //     href = decodeURIComponent(href);
    //     if (!href || href.length === 0) {
    //         if (!location) return;
    //         href = location.href;
    //     }
    //     const url = href.split('#');
    //     let href_search = '';
    //     if (/\?/.test(url[0])) {
    //         href_search = url[0].split('?')
    //     } else {
    //         href_search = ['', url[0]]
    //     }
    //
    //     let protocol_host_pathname = href_search[0].split('://');
    //     if (!/^https?:\/\//ig.test(href_search[0])) {
    //         protocol_host_pathname.unshift('')
    //     }
    //     const host_pathname = protocol_host_pathname[1].split('/'),
    //         hostname_post = host_pathname[0].split(':');
    //     this.location = {
    //         href: href,
    //         hash: url[1] ? '#' + url[1] : '',
    //         host: host_pathname[0] || '',
    //         hostname: hostname_post[0] || '',
    //         origin: host_pathname[0] ? (protocol_host_pathname[0] + '://' + host_pathname[0]) : '',
    //         pathname: host_pathname[1] ? ('/' + host_pathname.slice(1).join('/')) : '',
    //         port: hostname_post[1] || '',
    //         protocol: protocol_host_pathname[0] || '',
    //         search: href_search[1] ? ('?' + href_search[1]) : ''
    //     };
    //     return this.location;
    // }
}

export const qs = new QueryString();

export function camelLowerCaseES6 (str) {
    const re = /([A-Z])/g;
    return str.replace(re, function ($0, $1) {
        return `-${$1.toLowerCase()}`;
    });
}

export function camelUpperCaseES6 (str) {
    let re = /-(\w)/g;
    return str.replace(re, function ($0, $1) {
        return $1.toUpperCase();
    });
}

/**
 * 样式转对象
 * @param style
 * @returns {any}
 */
export const style2object = function (style) {
    if (!style || style === '' || typeof style !== "string") return;
    let Arr = style.split(';');
    Arr = Arr.filter(item => item !== '');
    let str = '';
    Arr.forEach(item => {
        let test = '';
        trim(item).split(':').forEach(item2 => {
            test += '"' + trim(item2) + '":'
        });
        str += test + ','
    });
    str = str.replace(/:,/g, ',');
    str = str.substring(0, str.lastIndexOf(','));
    str = '{' + str + '}';
    return JSON.parse(str)
}

/**
 * 对象转样式
 * @param obj
 * @returns {string|(string|string)}
 */
export const object2style = function (obj) {
    if (!jude.isEmptyObject(obj)) {
        for (const key in obj) {
            if (/[A-Z]/g.test(key)) {
                obj[camelLowerCaseES6(key)] = obj[key];
                delete obj[key]
            }
        }
        return qs.stringify(obj, {
            eq: ':',
            sep: ';',
            isEncode: false
        })
    }
    return ''
}

export const date = {
    format: require('./date/format').default,
    range: require('./date/range').default
};


export function mapKeysData (source, target, map, bol) {
    if (!map) return;
    if (Array.isArray(map)) {
        map.forEach(key => {
            if (!jude.isEmpty(source[key]) && typeof key === 'string') {
                target[key] = source[key];
                bol && delete source[key];
            } else if (Array.isArray(key) && key.length > 1 && typeof key[0] === 'string' && typeof key[1] === 'string' && !jude.isEmpty(source[key[0]])) {
                target[key[1]] = source[key[0]];
                bol && delete source[key];
            }
        });
    } else if (typeof map === 'boolean') {
        Object.keys(source).forEach(key => {
            if (!jude.isEmpty(source[key])) {
                target[key] = source[key];
                bol && delete source[key]
            }
        });
    } else {
        Object.keys(map).forEach(key => {
            if (!jude.isEmpty(source[key])) {
                target[map[key]] = source[key];
                bol && delete source[map[key]]
            }
        });
    }
}

export function mapKeys (source, target, map = [], opts = {}) {
    if (!map) return;
    let isDelete = false, isBasicData = false;
    if (typeof opts === "boolean") isDelete = opts;
    else if (jude.isObject(opts)) {
        if (jude.isBoolean(opts.isDelete)) isDelete = opts.isDelete;
        if (jude.isBoolean(opts.isBasic)) isBasicData = opts.isBasic;
    }
    if (Array.isArray(map)) {
        map.forEach(key => {
            if (!jude.isEmpty2(source[key]) && typeof key === 'string') {
                target[key] = source[key];
                isDelete && delete source[key];
            } else if (Array.isArray(key) && key.length > 1 && typeof key[0] === 'string' && typeof key[1] === 'string' && !jude.isEmpty(source[key[0]])) {
                target[key[1]] = source[key[0]];
                isDelete && delete source[key];
            }
        });
    } else if (typeof map === 'boolean' && map === true) {
        Object.keys(source).forEach(key => {
            if (!jude.isEmpty(source[key])) {
                target[key] = source[key];
                isDelete && delete source[key]
            }
        });
    } else if (jude.isObject(map)) {
        Object.keys(map).forEach(key => {
            if (!jude.isEmpty(source[key])) {
                target[map[key]] = source[key];
                isDelete && delete source[map[key]]
            }
        });
    }
    return target;
}

export function getDate (dateStr) {
    const dateArr = dateStr.split(/[- : \/]/);
    return new Date(+dateArr[0], +dateArr[1] - 1, dateArr[2] || '01', dateArr[3] || '00', dateArr[4] || '00', dateArr[5] || '00');
}

export function strLength (input, max) {
    if (jude.isString(input) || (jude.isNumber(max) && max > 0)) {
        if (jude.isNumber(input)) input = input + '';
        let arr = [];
        let len = 0;
        for (let i = 0; i < input.length; i++) {
            let a = input.charAt(i);
            if (a.match(/[^\x00-\xff]/ig) != null) {
                len += 1.6
            } else {
                len += 1
            }
            if (jude.isNumber(max) && len > max) {
                break
            } else {
                arr.push(a)
            }
        }
        if (!jude.isNumber(max)) return len;
        if (input.length === arr.length) return arr.join('');
        return arr.join('') + '...';
    } else if (jude.isNumber(max)) {
        return false;
    } else {
        return 0;
    }
}

let timer_toast = false;

function getToastData (opts) {
    let data = {
        icon: 'success',
        mask: true,
        duration: 1500
    };
    if (typeof opts === 'string') {
        data.title = opts;
        let start = 1;
        if (jude.isString(arguments[start]) && ['success', 'loading', 'none'].indexOf(arguments[start]) > -1) {
            data.icon = arguments[start];
            start++;
        }
        if (jude.isFunction(arguments[start])) {
            data.complete = arguments[start];
            start++
        }
        if (jude.isFunction(arguments[start])) {
            data.success = arguments[start];
            start++
        }
        if (jude.isFunction(arguments[start])) {
            data.fail = arguments[start]
            start++
        }
    } else if (jude.isObject(opts) && !jude.isEmptyObject(opts) && opts.title) {
        mapKeys(opts, data, ['duration', 'icon', 'image', 'success', 'fail', 'complete']);
        data.title = opts.title;
    } else return {};
    return data;
}

export function showToast (opts) {
    if (timer_toast) return;
    timer_toast = true;
    let data = getToastData(...arguments);
    if (!data.title) return;
    const complete = data.complete;
    data.complete = function () {
        timer_toast = false;
        typeof complete === 'function' && complete(...arguments);
    };
    if (strLength(data.title) > 7) {
        delete data.image;
        data.icon = 'none'
    }
    uni.showToast(data)
}

export function textToast (opts) {
    let data = getToastData(...arguments);
    data.icon = 'none';
    showToast(data)
}

export function failToast (opts) {
    let failIcon = '/static/image/toast_fail.png';
    // #ifdef H5
    failIcon = require('../static/image/toast_fail.png');
    // #endif
    let data = getToastData(...arguments);
    data.image = failIcon;
    showToast(data)
}

export function showLoading (opts) {
    let data = {
        title: '加载中...',
        mask: true
    };
    if (jude.isFunction(opts) || jude.isString(opts)) {
        let start = 0;
        if (jude.isString(arguments[start])) {
            data.title = arguments[start];
            start++;
        }
        if (jude.isFunction(arguments[start])) {
            data.complete = arguments[start];
            start++
        }
        if (jude.isFunction(arguments[start])) {
            data.success = arguments[start];
            start++
        }
        if (jude.isFunction(arguments[start])) {
            data.fail = arguments[start]
            start++
        }
    } else if (jude.isObject(opts) && !jude.isEmptyObject(opts) && opts.title) {
        mapKeys(opts, data, ['success', 'fail', 'complete']);
        if (opts.title) data.title = opts.title;
    }
    uni.showLoading(data);
}

export function getRegExp (str) {
    return new RegExp(str)
}

export function absUrl (url, imgw, bol = true) {
    if (typeof url === "string") {
        const reg = /^https?:\/\//i;
        const reg0 = /^blob:https?:\/\//i;
        const reg1 = /^wxfile:\/\//i;
        const reg2 = /^wxftp:\/\//i;
        const reg3 = /^data:image\/(\w+);base64,/i;
        const reg4 = /^\/h5\//i;

        const isBaseUrl = reg0.test(url) || reg1.test(url) || reg2.test(url) || reg3.test(url) || reg4.test(url);


        const qnReg = /^https?:\/\/qn/i;
        let qnTxt = 'imageView2/5';
        let qnTxt2 = 'imageMogr2/thumbnail';

        const imageView2 = /(imageView2|imageMogr2)/;
        const imageMogr2 = /imageMogr2/;
        const rg = getRegExp('[0-9]{1,}(,|x)[0-9]{1,}');
        const rg1 = getRegExp(',|x');
        const rg2 = getRegExp('^![0-9]{1,}p$');

        if (isBaseUrl) return reg2.test(url) ? url.replace(/^wxftp:/, '') : url;
        if (imgw) {
            if (typeof imgw === 'boolean') {//图片清除缓存
                if (url.indexOf('?') === -1) {
                    url += '?'
                } else {
                    url += '&'
                }
                url += '_t=' + new Date().getTime()
            } else if (jude.isNumberOfNaN(imgw)) { //指定图片宽度
                qnTxt += imageView2.test(url) ? '' : `/w/${imgw}/h/${imgw}`;
                if (!qnReg.test(url)) url += `!${imgw}x${imgw}`
            } else if (typeof imgw === "string" && rg.test(imgw)) {
                let [w, h] = imgw.split(rg);
                if (w > 0 && h > 0) {
                    qnTxt += imageView2.test(url) ? '' : `/w/${w}/h/${h}`;
                    if (!qnReg.test(url)) url += `!${w}x${h}`;
                }
            } else if (typeof imgw === "string" && rg2.test(imgw) && qnReg.test(url)) {
                qnTxt = qnTxt2 + '/' + imgw
            }
        } else if (!imageView2.test(url)) {
            qnTxt = qnTxt2 + '/!80p'
        }
        if (qnReg.test(url) && !imageView2.test(url)) {
            const p = imageMogr2.test(qnTxt) ? 'quality' : 'q';
            if (jude.isNumberOfNaN(bol)) {
                qnTxt += `/${p}/${bol}`
            } else if (bol === true) {
                qnTxt += `/${p}/50`
            }
            return url + '?' + qnTxt
        } else if (reg.test(url)) {
            return url
        } else {
            if (!/^\//.test(url)) url = `/${url}`;
            return config.imageUrl + url
        }
    } else {
        return "url"
    }
}

export function signOut () {
    Vue.$store && Vue.$store.commit('System/removeUserInfo');
    return new Promise(resolve => {
        uni.getStorageInfo({
            success: async function (res) {
                for (let val of res.keys) {
                    if (config.NO_REMOVE_STORAGE.indexOf(val) === -1) {
                        uni.removeStorage({
                            key: val
                        })
                    }
                }
                await Vue.$Storage.clearExpiredStorageSync()
                await Vue.$Storage.clearInterimStorageSync()
                await Vue.$Storage.clearInterimStorageSync("home")
                Vue.$global_util.Login.removeLogin()
                resolve();
            },
            fail: resolve
        });
    })
};

export function getCurrentPage (page = 0) {
    page = Math.abs(page);
    const pages = getCurrentPages();
    if (!jude.isEmptyArray(pages)) {
        return pages[pages.length - (page + 1)] || {};
    } else {
        return {}
    }
}

export function getCurrentPageSync (num = 0) {
    try {
        const page = getCurrentPage(num);
        if (!jude.isEmptyArray(page)) return Promise.resolve(page);
        return new Promise(resolve => {
            setTimeout(function () {
                resolve(getCurrentPage(num))
            }, 300)
        })
    } catch (e) {
        return Promise.resolve({});
    }
}

export async function getLastPageSync (page = 1) {
    if (page < 1 || !page) page = 1;
    const lastPage = await getCurrentPageSync(page);
    if (lastPage.$vm) {
        lastPage.$vm.route = lastPage.route;
        return Promise.resolve(lastPage.$vm)
    } else {
        return Promise.resolve(lastPage)
    }
}

export function isLoginExpired () {
    const userInfo = Vue.$store.state.System.userInfo;
    let status = 0;
    if (!jude.isEmpty(userInfo)) {

    }
    return status;
}

export const getBasicUserInfoSync = function (bol = true, callback) {
    getBasicUserInfo(bol, callback);
};

/**
 * 获取用户基本信息与状态
 */
export const getBasicUserInfo = debounce(function (bol = false, callback) {
    return Vue.$ajax.Temp.getBasicUserInfo({}, bol).finally(result => {
        callback && typeof callback === "function" && callback(result);
    })
}, 500);

/**
 * 去重
 * @param arr
 * @param evalStr
 * @returns {*}
 */
export const unique = function (arr, evalStr) {
    const res = new Map();
    return arr.filter(a => {
        let str = a
        try {
            if (typeof a !== 'string' && evalStr && !!evalStr.replace(/^\s|\s$/g, '')) str = eval('a.' + evalStr)
        } catch (e) {

        }
        return !res.has(str) && res.set(str, 1)
    })
};

export const trim = function (string = '') {
    if (typeof string === 'string') {
        const reg = new RegExp('(^[\\s\\t\\xa0\\u3000]+)|([\\u3000\\xa0\\s\\t]+\x24)', 'g')
        return string.replace(reg, '')
    } else {
        return ""
    }
};

export const closePage = function () {
    if (Vue.$device.isWechat) {
        //#ifdef H5
        // 以下代码是用javascript强行关闭当前页面
        let opened = window.open('about:blank', '_self');
        opened.opener = null;
        opened.close();
        //#endif
    } else {
        //#ifdef MP-WEIXIN
        uni.switchTab({
            url: '/pages/home/index',
            complete () {
                uni.navigateBack({delta: -1})
            }
        })
        //#endif
    }
};

/**
 * 给URL添加参数
 * @param url
 * @param query
 * @returns {*}
 */
export const addToUrlQuery = function (url, query = {}) {
    let hash = '';
    if (jude.isEmptyObject(query, true) || typeof url !== "string") return url;
    if (/\?/g.test(url)) {
        let [host, q] = url.split('?');
        if (typeof q === "string" && q.indexOf('#') > -1) {
            [q, hash] = q.split('#');
        }
        q += '&' + qs.stringify(query);
        url = host + '?' + q;
        if (!jude.isEmpty(hash)) url += '#' + hash;
        return url;
    } else {
        return `${url}?${qs.stringify(query)}`;
    }
};

const ApJSBridgeAsyncReady = new Promise((resolve, reject) => {
    let flag = false;
    //#ifdef H5
    if (window.AlipayJSBridge) {
        resolve()
    } else {
        document.addEventListener('AlipayJSBridgeReady', resolve, false);
    }
    flag = true;
    //#endif
    flag === false && reject();
});

export const ApJSBridge = function () {
    const [port, opts, callback] = !jude.isEmpty(arguments) ? arguments : [];
    if (typeof port === "string") {
        ApJSBridgeAsyncReady.then(res => {
            window.AlipayJSBridge.call(port, opts, callback)
        }).catch(err => {

        });
    }
};

export const getNumber = function (num, def) {
    return jude.isNumberOfNaN(num) ? +num : def
};

/**
 * 生成从minNum到maxNum的随机数。
 * 如果指定decimalNum个数，则生成指定小数位数的随机数
 * 如果不指定任何参数，则生成0-1之间的随机数。
 * @param maxNum [数据类型是Integer]生成的随机数的最小值（minNum和maxNum可以调换位置）
 * @param minNum [数据类型是Integer]生成的随机数的最大值
 * @param decimalNum [数据类型是Integer]如果生成的是带有小数的随机数，则指定随机数的小数点后的位数
 * @return {string|number}
 */
export const randomNum = function (maxNum, minNum, decimalNum) {
    let max = 0, min = 0;
    minNum <= maxNum ? (min = minNum, max = maxNum) : (min = maxNum, max = minNum);
    switch (arguments.length) {
        case 1:
            return Math.floor(Math.random() * (max + 1));
        case 2:
            return Math.floor(Math.random() * (max - min + 1) + min);
        case 3:
            return (Math.random() * (max - min) + min).toFixed(decimalNum);
        default:
            return Math.random();
    }
};


/**
 * 产生一个随机的rgb颜色
 * @return {String}  返回颜色rgb值字符串内容，如：rgb(201, 57, 96)
 */
export function randomColor () {
    // 随机生成 rgb 值，每个颜色值在 0 - 255 之间
    let r = randomNum(0, 256),
        g = randomNum(0, 256),
        b = randomNum(0, 256);
    // 连接字符串的结果
    return "rgb(" + r + "," + g + "," + b + ")";
}


/**
 * 产生一个随机的图片
 * @return {String}
 */
export function randomImage () {
    return `https://qn.mmtcapp.com/static/image/robot/avatar/aratar_${randomNum(0, 1600)}.jpg`;
}

export const number_filter = function (e) {
    //先把非数字的都替换掉，除了数字和.
    e = e.replace(/[^\d\.]/g, '')
    //必须保证第一个为数字而不是.
    e = e.replace(/^\./g, '0.')
    //保证只有出现一个.而没有多个.
    e = e.replace(/\.{2,}/g, '.')
    //保证.只出现一次，而不能出现两次以上
    e = e.replace('.', '$#$').replace(/\./g, '').replace('$#$', '.')
    //只能输入两个小数
    e = e.replace(/^(\-)*(\d+)\.(\d\d).*$/, '$1$2.$3')
    return e
}

export const number_format = function (number, decimals = 2, dec_point, thousands_sep) {
    /*
     * 参数说明：
     * number：要格式化的数字
     * decimals：保留几位小数
     * dec_point：小数点符号
     * thousands_sep：千分位符号
     * */
    number = (number + '').replace(/[^0-9+-Ee.]/g, '')
    let n = !isFinite(+number) ? 0 : +number,
        prec = !isFinite(+decimals) ? 0 : Math.abs(decimals),
        sep = (typeof thousands_sep === 'undefined') ? '' : thousands_sep,
        dec = (typeof dec_point === 'undefined') ? '.' : dec_point,
        s = '',
        toFixedFix = function (n, prec) {
            let k = Math.pow(10, prec)
            return '' + Math.round(n * k) / k
        }
    s = (prec ? toFixedFix(n, prec) : '' + Math.round(n)).split('.')
    let re = /(-?\d+)(\d{3})/
    while (re.test(s[0]) && sep) {
        s[0] = s[0].replace(re, '$1' + sep + '$2')
    }

    if ((s[1] || '').length < prec) {
        s[1] = s[1] || ''
        s[1] += new Array(prec - s[1].length + 1).join('0')
    }
    return s.join(dec)
}

export const money_format = function (number) {
    let symbol = ''
    let money = null
    if (number >= 100000000) {
        money = number_format(number / 100000000, 2, undefined, ',')
        symbol = '亿'
    } else if (number >= 10000000) {
        money = number_format(number / 10000000, 2, undefined, ',')
        symbol = '千万'
    } else if (number >= 1000000) {
        money = number_format(number / 1000000, 2, undefined, ',')
        symbol = '百万'
    } else if (number >= 10000) {
        money = number_format(number / 10000, 2, undefined, ',')
        symbol = '万'
    } else {
        money = number_format(number, 2, undefined, ',')
    }
    if (money !== undefined) {
        return `${money.replace(/(\.00)$/, '')}${symbol}`
    } else {
        return number
    }
}

/**
 * 数字格式化
 * 参数说明：
 * @param num 要格式化的数字
 * @param decimals 保留几位小数
 * @param thousands 千分位位数
 * @param dec_point 小数点符号
 * @param thousands_sep 千分位符号
 * @param isInt 是否为整数
 * @param length 长度
 */
export const number_format2 = function (num, {decimals = 2, thousands = 3, dec_point = '.', thousands_sep = ',', isInt, length} = {}) {
    if (length > 0) {
        num = num.substring(0, length)
    }
    let arr = num.split('.')
    let decimal = ''
    thousands = parseInt(thousands)
    if (isNaN(thousands)) thousands = 3
    const reg = new RegExp(`(\\d{1,${thousands}})(?=(\\d{${thousands}})+(\\.\\d*)?$)`, 'g')
    let integer = arr[0].replace(/[^\d]/g, '').replace(reg, `$1${thousands_sep || ''}`)
    if (arr.length > 1 && !isInt) {
        decimal = arr[1].replace(/[^\d]/g, '')
        if (decimal !== 0) {
            if (decimals > 0) decimal = decimal.substring(0, decimals)
            decimal = (dec_point || '') + decimal
            if (!integer) integer = 0
        }
    }
    let n = integer + decimal
    return n
}

export const login = function (bol = false) {
    return new Promise((resolve, reject) => {
        uni.login({
            complete (loginRes) {
                let {code, errMsg} = loginRes;
                if (/ok/.test(errMsg)) {
                    resolve(loginRes)
                } else {
                    reject();
                }
            }
        })
    })
};

// 秒定时器
let second_interval_global;

export const openSecondInterval = function () {
    clearInterval(second_interval_global);
    second_interval_global = setInterval(function () {
        uni.$emit('second_interval_global')
    }, 1000)
};
export const clearSecondInterval = function () {
    clearInterval(second_interval_global);
};

let timer_timeout_global;
export const $$$setTimeout = function (func, d) {
    clearTimeout(timer_timeout_global);
    timer_timeout_global = setTimeout(func, d)
};

const GlobalModals = {
    Modals: [],
    set modals (key) {
        if (jude.isEmpty(key) || typeof key !== "string") return;
        const modals = this.modals;
        if (modals.indexOf(key) > -1) return;
        modals.push(key);
        Storage.setStorageSync('global-modals', unique(modals))
    },
    get modals () {
        const modals = Storage.getStorageSync('global-modals');
        if (!modals || !jude.isArray(modals)) return [];
        return modals;
    },
    getModals (key) {
        if (jude.isEmpty(key) || typeof key !== "string") return false;
        const modals = this.modals;
        console.log(modals.indexOf(key), key);
        return modals.indexOf(key) > -1;
    }
};

export const showGlobalModal = function (key, func) {
    if (jude.isEmpty(key) || typeof key !== "string") return Promise.resolve(false);
    const k = `${key}-${GlobalModals.Modals.length}`;
    GlobalModals.Modals.push({key: k, func});
    debounce(function () {
        for (let v of GlobalModals.Modals) {
            const [v1, index] = v.key.split('-');
            if (!GlobalModals.getModals(v1)) {
                typeof v.func === "function" && v.func(GlobalModals.Modals.indexOf(v) === +index);
                break;
            }
        }
        GlobalModals.Modals = [];
    }, 500)();
};

export const addGlobalModal = function (key) {
    GlobalModals.modals = key;
};
//使用递归的方式实现数组、对象的深拷贝
export const deepClone1 = function (obj) {
    //判断拷贝的要进行深拷贝的是数组还是对象，是数组的话进行数组拷贝，对象的话进行对象拷贝
    let objClone = Array.isArray(obj) ? [] : {};
    //进行深拷贝的不能为空，并且是对象或者是
    if (obj && typeof obj === "object") {
        for (let key in obj) {
            if (obj.hasOwnProperty(key)) {
                if (obj[key] && typeof obj[key] === "object") {
                    objClone[key] = deepClone1(obj[key]);
                } else {
                    objClone[key] = obj[key];
                }
            }
        }
    }
    return objClone;
};


export const openShareModalSync = async function ({shareList, isInternal, title} = {}) {
    const page = await getCurrentPageSync();
    const obj = arguments[0];
    if (page.$vm) {
        const vm = page.$vm;
        return new Promise((resolve, reject) => {
            if (!vm.$refs.footerBar) return reject();
            vm.$refs.footerBar.openShareModal({
                ...obj,
                success () {
                    obj && typeof obj.success === "function" && obj.success(...arguments);
                    resolve(...arguments)
                },
                fail () {
                    obj && typeof obj.fail === "function" && obj.fail(...arguments);
                    resolve(...arguments)
                },
                complete () {
                    obj && typeof obj.complete === "function" && obj.complete(...arguments);
                }
            })
        });
    } else {
        return Promise.reject();
    }
};


export const openAlertModalSync = async function ({title, isHtml, content, showCancel, cancelText, cancelColor, confirmText, confirmColor, contentColor, contentAlign, success, fail, complete}) {
    const page = await getCurrentPageSync();
    const args = arguments[0]
    if (page.$vm) {
        const vm = page.$vm;
        return new Promise((resolve, reject) => {
            if (!vm.$refs.footerBar) return reject();
            vm.$refs.footerBar.openAlertModal({
                ...args,
                success () {
                    args && typeof args.success === "function" && args.success(...arguments);
                    resolve(...arguments)
                },
                fail () {
                    args && typeof args.fail === "function" && args.fail(...arguments);
                    resolve(...arguments)
                },
                complete () {
                    args && typeof args.complete === "function" && args.complete(...arguments);
                }
            })
        });
    } else {
        return Promise.reject();
    }
};


export function arrShuffle (arr) {
    let i = arr.length;
    while (i) {
        let j = Math.floor(Math.random() * i--);
        [arr[j], arr[i]] = [arr[i], arr[j]];
    }
    return arr;
}

/**
 * 异步确认弹窗
 * @param title
 * @param content
 * @param showCancel
 * @param cancelText
 * @param cancelColor
 * @param confirmText
 * @param confirmColor
 * @returns {Promise<unknown>}
 */
export function showModalSync ({title, content, showCancel, cancelText, cancelColor, confirmText, confirmColor = '#0075FF'} = {}) {
    const obj = arguments[0];
    return new Promise((resolve, reject) => {
        uni.showModal({
            ...obj,
            success: resolve,
            fail: resolve
        })
    })
}

// 将rgb颜色转成hex
export function colorRGBtoHex (color) {
    if (typeof color !== "string")
        return `rgba(${color.r},${color.g},${color.b},${color.a})`
    let rgb = color.split(',');
    let r = parseInt(rgb[0].split('(')[1]);
    let g = parseInt(rgb[1]);
    let b = parseInt(rgb[2].split(')')[0]);
    return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
}

// 将hex颜色转成rgb
export function hexToRgba (hex, opacity) {
    let RGBA = "rgba(" + parseInt("0x" + hex.slice(1, 3)) + "," + parseInt("0x" + hex.slice(3, 5)) + "," + parseInt("0x" + hex.slice(5, 7)) + "," + opacity + ")";
    return {
        red: parseInt("0x" + hex.slice(1, 3)),
        green: parseInt("0x" + hex.slice(3, 5)),
        blue: parseInt("0x" + hex.slice(5, 7)),
        rgba: RGBA
    }
}
